package com.xinyue.cross.server.client;

import com.xinyue.cross.server.client.model.GameServerConnectionModel;
import com.xinyue.cross.server.client.model.GameServerMetaData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

public class GameServerConnectionService {
    private Map<String, List<GameServerConnectionModel>> gameServerConnectionModelMap = new ConcurrentHashMap<>(10);
    private Logger logger = LoggerFactory.getLogger(GameServerConnectionService.class);
    @Autowired
    private ApplicationContext context;

    /**
     * 清理不在注册列表的服务
     *
     * @param gameServerMetaDataMap
     */
    private void clearUnregisterGameServer(Map<String, List<GameServerMetaData>> gameServerMetaDataMap) {
        Map<String, List<GameServerConnectionModel>> gameServerConnectionMapTemp = new ConcurrentHashMap<>();
        gameServerConnectionModelMap.forEach((serviceId, connectionModelList) -> {
            List<GameServerMetaData> gameServerMetaData = gameServerMetaDataMap.get(serviceId);
            if (gameServerMetaData != null) {
                Map<String, GameServerMetaData> gameServerMetaDataInstanceMap = gameServerMetaData.stream().collect(Collectors.toMap(GameServerMetaData::getServiceKey, c -> c));
                List<GameServerConnectionModel> gameServerConnectionModelList = new ArrayList<>(4);
                for (GameServerConnectionModel connectionModel : connectionModelList) {
                    String serviceKey = connectionModel.getServiceKey();
                    GameServerMetaData metaData = gameServerMetaDataInstanceMap.get(serviceKey);
                    if (metaData != null) {
                        gameServerConnectionModelList.add(connectionModel);
                    } else {
                        logger.info("服务已掉线，清理掉，instanceName: {},serviceKey: {}", connectionModel.getInstanceName(), serviceKey);
                        if (connectionModel.getNettyClientService() != null) {
                            connectionModel.getNettyClientService().close(context);
                        }
                    }
                }
                if (!gameServerConnectionModelList.isEmpty()) {
                    gameServerConnectionMapTemp.put(serviceId, connectionModelList);
                }
            }
        });
        this.gameServerConnectionModelMap = gameServerConnectionMapTemp;
    }

    private GameServerConnectionModel findSameConnection(GameServerMetaData metaData) {
        String serviceKey = metaData.getServiceKey();
        List<GameServerConnectionModel> gameServerConnectionModelList = this.gameServerConnectionModelMap.get(serviceKey);
        if (gameServerConnectionModelList != null) {
            return gameServerConnectionModelList.stream().filter(c -> c.getServiceKey().equals(serviceKey)).findAny().orElse(null);
        }
        return null;
    }

    public void createConnectionClient(Map<String, List<GameServerMetaData>> gameServerMetaDataMap) {
        this.clearUnregisterGameServer(gameServerMetaDataMap);
        if (gameServerMetaDataMap.isEmpty()) {
            logger.warn("没有注册的服务，不创建服务连接");
            return;
        }
        Map<String, List<GameServerConnectionModel>> gameServerConnectionModelMapTemp = new ConcurrentHashMap<>(gameServerConnectionModelMap.size());
        gameServerMetaDataMap.forEach((serviceId, metaDataList) -> {
            List<GameServerConnectionModel> gameServerConnectionModelList = new ArrayList<>(metaDataList.size());
            for (GameServerMetaData metaData : metaDataList) {
                try {
                    if (metaData.getSocketPort() == 0) {
                        logger.warn("此服务没有设置长连接端口，不创建连接,serviceName: {}", metaData.getInstanceName());
                        continue;
                    }

                    GameServerConnectionModel connectionModel = this.findSameConnection(metaData);
                    if (connectionModel != null) {
                        logger.info("已存在此服务的连接，直接加入,instanceName: {}", metaData.getInstanceName());
                        gameServerConnectionModelList.add(connectionModel);
                    } else {
                        NettyClientService nettyClientService = this.createNettyClient(metaData);
                        connectionModel = new GameServerConnectionModel();
                        connectionModel.setInstanceName(metaData.getInstanceName());
                        connectionModel.setNettyClientService(nettyClientService);
                        gameServerConnectionModelList.add(connectionModel);
                    }
                } catch (Throwable e) {
                    logger.error("创建游戏服务连接失败，metadata: {}", metaData, e);
                }
            }
            gameServerConnectionModelMapTemp.put(serviceId, gameServerConnectionModelList);
        });
        this.gameServerConnectionModelMap = gameServerConnectionModelMapTemp;
    }


    private NettyClientService createNettyClient(GameServerMetaData metaData) throws InterruptedException {
        NettyClientService nettyClientService = new NettyClientService(metaData.getHost(), metaData.getSocketPort());
        nettyClientService.connect(context);
        return nettyClientService;
    }

    public Map<String, List<GameServerConnectionModel>> getGameServerConnectionModelMap() {
        return gameServerConnectionModelMap;
    }
}
